package genetic;

import genetic.individual.MarioIndividual;
import genetic.operators.CrossoverNPoints;
import genetic.operators.CrossoverUniform;
import genetic.operators.MarioOperator;
import genetic.operators.MutationFlip;
import genetic.operators.MutationSinglePoint;
import genetic.population.MarioPopulation;
import genetic.selection.MarioSelection;
import genetic.selection.MarioSelectionTournament;
import genetic.stopCondition.MarioStopCondition;


public class GeneticStart {
	public static MarioIndividual runGenetic(){
		int popMax = 500;
		int numGenes = 200;
		int numStrips = 19;
		double crossProb = 0.9;
		double mutProb = 0.01;
		
		System.out.println("Genetic Algorithm for level generation");
		
		MarioPopulation<Double, MarioIndividual> pop = new MarioPopulation<>(popMax);
		System.out.println("Population added");
		
		for(int i = 0; i < popMax; i++){
			pop.insertIndividual(new MarioIndividual(numGenes, numStrips, true));
		}
		
		System.out.println("Population started");
		
//		MarioSelection<Double, MarioIndividual> sel = new MarioSelection<>(pop);
		
		MarioSelectionTournament<Double, MarioIndividual> sel = new MarioSelectionTournament<>(pop);
		
		System.out.println("Selection added");
		
		MarioOperator<Double, MarioIndividual> op = new MarioOperator<>(crossProb, mutProb);
		op.addCrossover(new CrossoverUniform<MarioIndividual>());
		op.addCrossover(new CrossoverNPoints<MarioIndividual>(7));
		op.addCrossover(new CrossoverNPoints<MarioIndividual>(8));
		op.addCrossover(new CrossoverNPoints<MarioIndividual>(9));
		op.addMutation(new MutationFlip<MarioIndividual>());
		op.addMutation(new MutationSinglePoint<MarioIndividual>(numStrips));
		
		System.out.println("Operators added");
		
		MarioStopCondition<Double, MarioIndividual> stop = new MarioStopCondition<>(pop,20000);
		
		System.out.println("Stop Condition added");
		
		GeneticAlgorithm<MarioIndividual> genetic = new GeneticAlgorithm<>(pop, sel, op, stop);
		MarioIndividual i = genetic.runGenetic();
		System.out.println("Fitness: " + i.eval());
		System.out.println(op.debugInfo());
		return i;
	}
}
